zsh -c 'set -xv' tells zsh to run an inline script that contains set -xv. After running set -xv, the script is finished and zsh exits (with the exit code of set). Just like zsh -c uname runs uname and finishes.
exec zsh ; set -xv tell the current shell to execute zsh in the current process, so whatever command that lays after will never be executed (and in anycase, that could only be after exec returns), as the shell won't be around anymore to execute them.
If you wanted to run a zsh interactive shell with the -v and -x options on, that would be:
zsh -xv
Or
zsh -o verbose -o xtrace
If you want to run set -xv when zsh is run interactively with DEBUGCLI=YES in your environment like as the answer you linked suggests you want to do, then you can just add:
if [[ $DEBUGCLI = YES ]]; then
set -o xtrace -o verbose
fi
To your ~/.zshrc, (at the very last line there if you don't want the rest of your ~/.zshrc being traced and logged).
In anycase, you can run set -xv and set +xv (or set -o xtrace -o verbose and set +o xtrace +o verbose) to turn that debugging on or off without having to restart a shell each time.
And if you wanted xtrace to only be in effect during the execution of the code you enter (and not for the execution of commands in hooks or zle widgets), you could set it at the end of the preexec() hook and unset it at beginning of the precmd() hook (with set +x 2> /dev/null).