Nice, but the Operate is slightly heavy handed. I think the following is both shorter and easier to understand:
In[7]:= Dot[heads, arguments] /. Times -> (#1[#2] &)
Out[7]= f[w] + g[x] + h[y] + k[z]
Of course, this will break if one of the arguments has head Times.
arguments = {w, x, y, z b};
In[18]:= Dot[heads, arguments] /. Times -> (Operate[##, 0] &)
During evaluation of In[18]:= Operate::argt: Operate called with 4 arguments; 2 or 3 arguments are expected. >>
Out[18]= f[w] + g[x] + h[y] + Operate[b, k, z, 0]
In[19]:= Dot[heads, arguments] /. Times -> (#1[#2] &)
Out[19]= b[k] + f[w] + g[x] + h[y]