exec is often used in shell scripts which mainly act as wrappers for starting other binaries. For example:
EXTRA_OPTIONS="-x -y -z"
exec /usr/local/bin/the.real.binary $EXTRA_OPTIONS "$@"
so that after the wrapper is finished running, the "real" binary takes over and there is no longer any trace of the wrapper script that temporarily occupied the same slot in the process table. The "real" binary is a direct child of whatever launched it instead of a grandchild.
You mention also I/O redirection in your question. That is quite a different use case of
exec and has nothing to do with replacing the shell with another process. When
exec has no arguments, like so:
then I/O redirections on the command line take effect in the current shell process, but the current shell process keeps running and moves on to the next command in the script.