docs: protected void launchTasks(List<LaunchableTask> tasks) {
      // Group the tasks by offer
      Map<Protos.Offer, List<LaunchableTask>> tasksGroupByOffer = new HashMap<>();
      for (LaunchableTask task : tasks) {
        List<LaunchableTask> subTasks = tasksGroupByOffer.get(task.offer);
        if (subTasks == null) {
          subTasks = new LinkedList<>();
        }
        subTasks.add(task);
        tasksGroupByOffer.put(task.offer, subTasks);
      }
  
      // Construct the Mesos TaskInfo to launch
      for (Map.Entry<Protos.Offer, List<LaunchableTask>> kv : tasksGroupByOffer.entrySet()) {
        // We would launch taks for the same offer at one shot
        Protos.Offer offer = kv.getKey();
        List<LaunchableTask> subTasks = kv.getValue();
  
        List<Protos.TaskInfo> mesosTasks = new LinkedList<>();
        for (LaunchableTask task : subTasks) {
          Protos.TaskInfo pTask = task.constructMesosTaskInfo(heronConfig, heronRuntime);
          mesosTasks.add(pTask);
        }
  
        LOG.info("Launching tasks from offer: " + offer + " with tasks: " + mesosTasks);
  
        // Launch the tasks for the same offer
        Protos.Status status =
            driver.launchTasks(Arrays.asList(new Protos.OfferID[]{offer.getId()}),
                mesosTasks);
  
        if (status == Protos.Status.DRIVER_RUNNING) {
          LOG.info(String.format("Tasks launched, status: '%s'", status));
  
        } else {
          LOG.severe("Other status returned: " + status);
  
          // Handled failed tasks
          for (LaunchableTask task : tasks) {
            handleMesosFailure(task.taskId);
            // No need to decline the offers; mesos master already reclaim them
          }
        }
      }
    }