Macros are easy to understand if you are shown that whatever language you are using
already has them. The difference is that they are locked in and wrapped behind at least two layers.
Firstly, there rigid surface syntax which customizes the look of every macro at the character level. For instance, in C, the do ... while(); loop must have a trailing semicolon. (No Lisp macro has such requirements.)
Secondly, that surface syntax translates to a limited set of abstract syntax tree forms which is not extensible.
Lisp macros open that up. The outer layer of varnish is stripped away, so any conceivable abstract syntax tree form has a notation; you do not have to invent new character-level surface syntax in order to work with a new form. And then, custom recognizers for arbitrary forms can be written by the language users, which do tree to tree transformations.
So then how you use these things once you have them is the same way that yu use the features of programming languages that you know.
E.g. loop is a macro in Lisp. We use it like this:
[1]> (loop for x from 1 to 10
for a = 2 then (* 2 a)
collect (list x a)))
((1 2) (2 4) (3 8) (4 16) (5 32) (6 64)
(7 128) (8 256) (9 512) (10 1024))
Someone wrote the loop macro, so in this situation I'm just a user. I don't care whether this is a macro, or built-in to the language like "foreach x in list do".
When I use loop, I'm benefiting from macro-writing.
The benefits are far-reaching. For instance, language experimentation takes place in the user base, not behind the closed doors of an ivory tower (ISO committee or whatever). Language ideas are packaged as code and shared around.
Technical problems turn into social problems, as someone noted.