По-хорошему приложение в django — юниксвей в чистом виде: делает что-то одно, делает это хорошо, обладает неким внешним API для взаимодействия с другими модулями. Обычно даже в небольшом проекте насчитывается около десятка приложений. Плюсы такого подхода — значительно легче тестировать, повторно использовать код, можно сравнительно безболезненно менять имплементацию модуля, не нарушая работу всего сайта.
Антипаттерн — монолитные приложения (обычно буквально одно-два). Их, помимо прочего, тяжелее поддерживать, поскольку код выполняет множество не связанных напрямую задач (функции, отвечающие за генерацию RSS и смену аватарки пользователя, находятся рядом — в таком файле ничего не получится сделать без поллитры и ctrl-F). Это особенно актуально, когда в команду добавляется новый разработчик.
Взаимодействие приложений — гораздо более обширная тема, ее вот так запросто в двух предложениях не раскрыть, как мне кажется.