Alex R. wrote this example program showing how the three different move types result in three different trajectories. Free moves (movef()) are the easiest for the controller to plan and generally the fastest to execute, but they are not deterministic, meaning they may not always follow the same path. Joint moves (movej()) are deterministic and always follow the same path. Linear moves (movel()) are of course linear - a straight line between the two waypoints. They are harder to plan and depending on the presence of collision models or attached end effectors the plan may not succeed.
In general I try to use joint moves whenever possible. In a recent welding application I prefer a joint move to the start of a taught weld sequence, followed by a linear move for the actual weld.
I found Alex’s use of the moveit_commander.PlanningSceneInterface() to create a rectangular box representing an obstacle that the robot needed to plan around really interesting. If people are interested we can do a more in-depth demonstration of that functionality.