def partition_app_list(app_list, n):
    """
    :param app_list: A list of apps with models.
    :param n: Number of buckets to divide into.
    :return: Partition apps into n partitions, where the number of models in each list is roughly equal. We also factor
    in the app heading.
    """
    num_rows = sum([1 + len(x['models']) for x in app_list]) # + 1 for app title
    num_rows_per_partition = num_rows / n

    result = [[] for i in range(n)] # start with n empty lists of lists
    partition = 0
    count = 0

    for a in app_list:
        # will the app fit in this column or overflow?
        c = len(a['models']) + 1 # the +1 is for the app title
        # if we're not on the last partition, and the models list fits
        # more on the next partition than this one, start the next partition.
        if (partition < n - 1) and (count + c/2.0 > num_rows_per_partition):
            partition += 1
            count = 0
        result[partition].append(a)
        count += c

    return result