Why is printf() bad for debugging embedded systems?
I can come up with a few disadvantages of using printf(). Keep in mind that "embedded system" can range from something with a few hundred bytes of program memory to a full-blown rack-mount QNX RTOS-driven system with gigabytes of RAM and terabytes of nonvolatile memory. 


It requires someplace to send the data. Maybe you already have a
debug or programming port on the system, maybe you don't. If you
don't (or the one you have is not working) it's not very handy. 
It's not a lightweight function in all contexts. This could be a big deal if you have
a microcontroller with only a few K of memory, because linking in printf might eat up 4K all by itself. If you have a 32K or 256K microcontroller, it's probably not an issue, let alone if you have a big embedded system. 
It's of little or no use for finding certain kinds of problems related to memory allocation or interrupts, and can change the behavior of the program when statements are included or not. 
It's pretty useless for dealing with timing-sensitive stuff. You'd be better off with a logic analyzer and an oscilloscope or a protocol analyzer, or even a simulator.
If you have a big program and you have to re-compile many times as you change printf statements around and change them you could waste a lot of time. 


What it's good for- it is a quick way to output data in a preformatted way that every C programmer knows how to use- zero learning curve. If you need to spit out a matrix for the Kalman filter you're debugging, it might be nice  to spit it out in a format that MATLAB could read in. Certainly better than looking at RAM locations one at a time in a debugger or emulator. 

I don't think it's a useless arrow in the quiver, but it should be used sparingly, along with gdb or other debuggers, emulators, logic analyzers, oscilloscopes, static code analysis tools, code coverage tools and so on.