When you do
y = z^2/2;
fz[z_] := y;
fz[3]
the delayed evaluation f[z_]:=y means that the right-hand side is memorized verbatim. You can check with ?fz
When you then call f[3], the replacement z->3 is done in the frozen y, resulting in no replacement at all, since the verbatim y does not contain z.
After this useless replacement y/.z->3 is done, the result is unfrozen, and the outside rule y=z^2/2 gets finally applied.