Thank you for taking the time to provide further explanation.
Your remarks clarify some of my confusion.
For example the List
s = {"a", "b", c, 5}
which only has one level, level 1, with the Head itself at level 0.
has the generalized Head of List so that Head[s] returns "List".
If what you say "replacing of all the heads with a different head", one might expect that the following
ToString @@@ s
would make the Heads Head[s[[1]]], Head[s[[2]]], Head[s[[3]]], Head[s[[4]]] all return "String".
However, in fact this seems only true for Head[s[[1]] and Head[s[[2]], which are already strings, whereas
Head[s[3]]] returns Symbol and Head[s[[4]]] returns Integer. It would seem that although all elements of List s taken together have a Head of String after the Apply at Level 1 function syntax is executed, each element within the list still retains its "atomic" [correct word?] character.
Thus, it seems that list s of the fundamental types is not, subsequent to the application of ToString @@@ s, a list of all elements with a Head of String, but still a list of mixed types [atoms?]. However, this behavior seems confined to when the expressions making up the elements of a list are atoms rather than functions.
However, in going through your example of Apply[f, {g[a], g[b], g[c]}, 1], I observe that as you and the documentation indicate
if we assign this to a list of functions, then Apply works exactly as you say. I can see I must think more carefully about what elements are in my list, expressions that may be atoms or expressions that may be functions.
Consequently, I think much of my confusion is that often the individual elements of my lists are of mixed type and hence iterating or mapping over them can often produce unexpected results when the functions I create are not properly overloaded and where I fail to appreciate the difference between a list of "atoms" and a list of functions serving as input.
As for your comment with respect to Timing, your approach seems about 4 times more efficient, if viewed this way:
In[92]:= Do[f @@@ {g[a], g[b], g[c]}, 100000] // Timing
{0.109375, Null}
Do[Map[Apply[f[#] &], {g[a],g[b], g[c]}], 100000] // Timing
{0.46875, Null}
and 11 times more efficient, if set up this way:
u = Table[g[a], {a 1, 100000}];
v = f @@@ {u}; // Timing
{0.015625, Null}
or this way,
y = Map[Apply[f[#]&, u] //Timing
{0.171875, Null}
presumably because of the cost of rebuilding the pure function each time in the list or processing them sequentially. This is something worth keeping in mind for long lists or for lists that are repeatedly iterated in some way.
So your suggestion seems not only to be cleaner but also more efficient.