fill применяется к каждому svg-объекту по отдельности, поэтому получается такой эффект.
Думаю, одним из самых простых решений будет использование маски.
То есть создаете один большой объект, который заливаете градиентом, а саму svg используете как маску для этого объекта.