Talking about differences between zsh and bash:
With quotes around $@ and $*, zsh and bash behave the same, and I guess the result is quite standard among all shells:
$ f () { for i in "$@"; do echo +"$i"+; done; }; f 'a a' 'b' ''
+a a+
+b+
++
$ f () { for i in "$*"; do echo +"$i"+; done; }; f 'a a' 'b' ''
+a a b +
Without quotes, results are the same for $* and $@, but different in bash and in zsh. In this case zsh shows some odd behaviour:
bash$ f () { for i in $*; do echo +"$i"+; done; }; f 'a a' 'b' ''
+a+
+a+
+b+
zsh% f () { for i in $*; do echo +"$i"+; done; }; f 'a a' 'b' ''
+a a+
+b+
(Zsh usually don't split textual data using IFS, unless explicitly requested, but notice that here the empty argument is unexpectedly missing in the list.)