Is it recommended to use a separate tf server (as in its own node)?
It's not the default way to do things. There are use cases when this can be valuable. In particular when you have something that only needs to query for transforms at a low rate, and can afford higher latency in your queries. You can use a tf2_ros::BufferServer class or the standalone buffer_server
node in conjunction with a tf2_ros::BufferClient in python or C++ to query the BufferServer. Using this when remote can save a lot of bandwidth and computation cycles.
Should URDF be used for statically-linked robots like quadcopters with a few attached sensors?
It can be quite convenient as the URDF captures more than just the joints. There are a lot of examples of this already. Take a look here: https://github.com/ethz-asl/rotors_si...
When is a tf_state_publisher used (from a launch file, say), as opposed to a tf broadcaster in code?
If you're publishing with a standalone command line tool where you pass the arguments to it at startup the transform must be fixed and unchanging. If you have it in code, the transform can updated based on information/logic in the code.
PS as a meta comment. Please try to ask your questions separately. I was able to answer all your questions, but in general different questions might have different people who will know the answer but you can only accept one answer.
Thanks. Will do.