Earlier quoted context omitted.
You "call" a module with arguments. You can call them multiple times. In every way that matters they are just like a function call. I don't understand why there is a distinction between for each in a standard language vs for_each in HCL2. They are both do something by iterating over something else at runtime. The syntax isn't what matters here. I think maybe you are mistaken in your own distinction between declarativ…
Imperative: Tell the computer how to do something, by instructing it what to do. Declarative: Tell the computer what you want the result to be like, and the computer figures out how to do it. for_each in Terraform is very much declarative, just like modules. Compare how you'd do the same thing with JS or any other (imperative) language you know, and I think it must be clear what the difference between the two is.
I have read terraform modules where I had to execute the logic to know what got produced which moves it from your imperative description to the declarative description as far as I'm concerned.