[SPARK-4737] Task set manager properly handles serialization errors

Dealing with [SPARK-4737], the handling of serialization errors should not be the DAGScheduler's responsibility. The task set manager now catches the error and aborts the stage.

If the TaskSetManager throws a TaskNotSerializableException, the TaskSchedulerImpl will return an empty list of task descriptions, because no tasks were started. The scheduler should abort the stage gracefully.

Note that I'm not too familiar with this part of the codebase and its place in the overall architecture of the Spark stack. If implementing it this way will have any averse side effects please voice that loudly.
Minor style point, but I think you can combine this assertion with the following one, which will give more informative error messages if the assertion fails (since now you'll see the difference in contents if the lengths are not equal):

```scala
assert(taskDescriptions.map(_.executorId) === Seq("executor0"))
```