A little spelunking may help:
$ lsof -d 0,1,2 -a -p $$
That will show you what files correspond to what file descriptors for your current shell process. You can then experiment with redirects. To see how a pipe works we can do something similar:
$ sleep 1 | lsof -d 0,1,2 -a -p $(sh -c 'echo $PPID')
Anyway, thinking of `>` and `<` as just FD setters made things a lot clearer for me personally. They just set the file descriptor on the left to file on the right and `&n` can be used to "dereference" a FD to its corresponding file. The only real difference between `>` and `<` is that the former opens the file with write permission while the latter opens it with read. Well, and the default FDs are different.
Incidentally, this makes it clear why the following doesn't work as expected:
$ curl 'https://kernel.org/' >/dev/null 2>&1 | tee curl.errs
Since FDs get set in the order they are specified, 1 gets set to /dev/null and then 2 gets set to whatever 1 is, i.e /dev/null. So it's clear that we probably intended the following:
$ curl 'https://kernel.org/' 2>&1 >/dev/null | tee curl.errs
Which lets us ignore stdin and maybe pipe stdout to some other command.
Now I hope Linus doesn't hate on me for abusing kernel.org :P