What is meant by "meta-level" in logic programming?

Yes, but call/n can be defined as a first-order thing (just add a corresponding call/n clause for every predicate in the program), so I don’t think of it as something special. Others might disagree.

“Thunk” is, I suppose an old-fashioned word for what is now called “closure” (although the definition of “closure” is somewhat variable, it seems) – basically, a pointer to code plus some environment. See also delimited continuations, which I don’t fully understand.

So, it might be useful to have something like term_closure/2 or term_callable/2 that maps between a term and something that can be called. Whether this would be more or less confusing than call/1, call/2, etc., I don’t know.

If you have the following code:

number_word(0, zero).
number_word(1, one).
number_word(2, two).
number_word(I, big) :- I > 2.

then there’s a predicate number_word/2 that has 4 clauses, and all of the clauses happen to have the syntax of a term (see: homoiconicity). There’s no intrinsic reason why this to be true – Picat, for example, does not represent its predicates in a form that is directly representable as terms. (Lisp is the canonical example of homoiconicity; but it has the opposite default from Prolog: everything is called unless specifically quoted (e.g., by the QUOTE special form)).

It’s convenient to have the same syntax for predicates and terms, for things like macro-expansion or program analysis (see clause/2) or for dynamically adding facts/rules (see assertz/1); but it also confuses beginners. (Does the similar thing in Lisp also confuse beginners?)